#include "syntax_parser.h"
#include "errors_warnings.h"

#include "main_container.h"
extern MainContainer * CompilerData;


// <numeric_mod> ~ discrete  {discrete}
// <numeric_mod> ~ continuous  {continuous}
void Parser::Parse_NumericMod(SyntaxTreeNode* parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_NumericMod");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	if(currentUnit.type==LUTypeKeyword && currentUnit.subtype==KeywordDiscrete)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"discrete\".");
#endif
		parent->Production = Gr_NumericMod__discrete;
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		CurrentLexicPosition++;
	}
	else if(currentUnit.type==LUTypeKeyword && currentUnit.subtype==KeywordContinuous)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"continuous\".");
#endif
		parent->Production = Gr_NumericMod__continuous;
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		CurrentLexicPosition++;
	}
	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_NUMERIC_MOD_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_NumericMod");
#endif
}

// <inf_end> ~ ; + INF  {;}
// <inf_end> ~ ? {}}
void Parser::Parse_InfEnd(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_InfEnd");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	if(currentUnit.type==LUTypeSpecialCharacter && currentUnit.subtype==SpecialCharacterSemicolon)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterSemicolon.");
#endif
		// write type of production in this node
		parent->Production = Gr_InfEnd__spSemiCol_opAdd_INF;

		// process terminal symbol ';' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		CurrentLexicPosition++;

		// process terminal symbol '+' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type==LUTypeOperator && currentUnit.subtype==OperatorAddition)
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized OperatorAddition.");
#endif
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			CurrentLexicPosition++;
		}
		else
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Error. Recovery is to skip this lexic unit.");
#endif
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_ADDITION_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process terminal symbol 'INF' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type==LUTypeKeyword && currentUnit.subtype==KeywordINF)
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized keyword \"INF\".");
#endif
			SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode2);
			newNode2->LexUnitID=this->CurrentLexicPosition;
			newNode2->Production=Gr_Terminal;
			CurrentLexicPosition++;
		}
		else
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Error. Recovery is to skip this lexic unit.");
#endif
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_INF_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}
	}
	else if(currentUnit.type==LUTypeSpecialCharacter && currentUnit.subtype==SpecialCharacterRightCurlyBrace)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterRightCurlyBrace.");
#endif
		// write type of production in this node
		parent->Production = Gr_InfEnd__epsilon;
	}
	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_INF_END_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_InfEnd");
#endif
}

// <value_pairs> ~ <value_pair> <value_pairs_adds>  {LITERAL, +, -}
// <value_pairs> ~ ? {;, }}
void Parser::Parse_ValuePairs(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_ValuePairs");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	if((currentUnit.type==LUTypeConstantBool || currentUnit.type==LUTypeConstantFloat || currentUnit.type==LUTypeConstantInteger) ||
		(currentUnit.type==LUTypeOperator && currentUnit.subtype==OperatorAddition) ||
		(currentUnit.type==LUTypeOperator && currentUnit.subtype==OperatorSubtraction))
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized OperatorAddition or OperatorSubtraction or LITERAL.");
#endif
		// write type of production in this node
		parent->Production = Gr_ValuePairs__ValuePair_ValuePairsAdds;

		// process nonterminal symbol <value_pair> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_ValuePair(newNode0);

		// process nonterminal symbol <value_pairs_adds> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_ValuePairsAdds(newNode1);
	}
	else if( (currentUnit.type==LUTypeSpecialCharacter && currentUnit.subtype==SpecialCharacterSemicolon) ||
		(currentUnit.type==LUTypeSpecialCharacter && currentUnit.subtype==SpecialCharacterRightCurlyBrace) )
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterSemicolon or SpecialCharacterRightCurlyBrace.");
#endif
		// write type of production in this node
		parent->Production = Gr_ValuePairs__epsilon;
	}
	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_VALUE_PAIRS_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_ValuePairs");
#endif
}

// <value_pair> ~ <sign_value> LITERAL -> <sign_value> LITERAL  {+, -, LITERAL}
void Parser::Parse_ValuePair(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_ValuePair");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	if((currentUnit.type==LUTypeConstantBool || currentUnit.type==LUTypeConstantFloat || currentUnit.type==LUTypeConstantInteger ) ||
		(currentUnit.type==LUTypeOperator && currentUnit.subtype==OperatorAddition) ||
		(currentUnit.type==LUTypeOperator && currentUnit.subtype==OperatorSubtraction))
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized OperatorAddition or OperatorSubtraction or LITERAL.");
#endif
		parent->Production = Gr_ValuePair__SignValue_LITERAL_spArrow_SignValue_LITERAL;

		// process nonterminal symbol <sign_value> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_SignValue(newNode0);

		// process terminal symbol 'LITERAL' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type==LUTypeConstantBool || currentUnit.type==LUTypeConstantFloat || currentUnit.type==LUTypeConstantInteger )
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized LITERAL.");
#endif
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Error. Recovery is to skip this lexic unit.");
#endif
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LITERAL_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process terminal symbol '->' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type==LUTypeSpecialCharacter && currentUnit.subtype==SpecialCharacterTheArrowOperator)
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterTheArrowOperator.");
#endif
			SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode2);
			newNode2->LexUnitID=this->CurrentLexicPosition;
			newNode2->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Error. Recovery is to skip this lexic unit.");
#endif
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_ARROW_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <sign_value> 
		SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode3);
		Parse_SignValue(newNode3);

		// process terminal symbol 'LITERAL' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type==LUTypeConstantBool || currentUnit.type==LUTypeConstantFloat || currentUnit.type==LUTypeConstantInteger)
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized lexic unit LITERAL.");
#endif
			SyntaxTreeNode * newNode4 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode4);
			newNode4->LexUnitID=this->CurrentLexicPosition;
			newNode4->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Error. Recovery is to skip this lexic unit.");
#endif
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LITERAL_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}
	}
	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_VALUE_PAIR_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_ValuePair");
#endif
}

// <value_pair_add> ~ ; <value_pair>  {;}
void Parser::Parse_ValuePairAdd(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_ValuePairAdd");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	if(currentUnit.type==LUTypeSpecialCharacter && currentUnit.subtype==SpecialCharacterSemicolon)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterSemicolon.");
#endif
		// write type of production in this node
		parent->Production = Gr_ValuePairAdd__spSemiCol_ValuePair;

		// process terminal symbol ';' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <value_pair> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_ValuePair(newNode1);
	}
	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_VALUE_PAIR_ADD_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_ValuePairAdd");
#endif
}

// <sign_value> ~ +  {+}
// <sign_value> ~ -  {-}
// <sign_value> ~ ? {LITERAL}
void Parser::Parse_SignValue(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_SignValue");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	if(currentUnit.type==LUTypeOperator && currentUnit.subtype==OperatorAddition)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized OperatorAddition.");
#endif
		// write type of production in this node
		parent->Production = Gr_SignValue__opAdd;

		// process terminal symbol '+' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

	}
	else if(currentUnit.type==LUTypeOperator && currentUnit.subtype==OperatorSubtraction)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized OperatorSubtraction.");
#endif
		// write type of production in this node
		parent->Production = Gr_SignValue__opSub;

		// process terminal symbol '-' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

	}
	else if(currentUnit.type==LUTypeConstantBool || currentUnit.type==LUTypeConstantFloat || currentUnit.type==LUTypeConstantInteger )
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized lexic unit LITERAL.");
#endif
		// write type of production in this node
		parent->Production = Gr_SignValue__epsilon;
	}
	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SIGN_VALUE_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_SignValue");
#endif
}

// <model_definition> ~ <model_mod> model <name> ( <parameters> ) <model_definition_in> <model_definition_out> { <model_body> }  {public, private, model}
void Parser::Parse_ModelDefinition(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_ModelDefinition");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	if( (currentUnit.type==LUTypeKeyword && currentUnit.subtype==KeywordPublic) || 
		(currentUnit.type==LUTypeKeyword && currentUnit.subtype==KeywordPrivate) || 
		(currentUnit.type==LUTypeKeyword && currentUnit.subtype==KeywordModel) )
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized one of keywords: \"public\", \"private\", \"model\".");
#endif
		// write type of production in this node
		parent->Production = Gr_ModelDefinition__ModelMod_model_Name_spLPar_Parameters_spRPar_ModelDefinitionIn_ModelDefinitionOut_spLCBrac_ModelBody_spRCBrac;

		// process nonterminal symbol <model_mod> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_ModelMod(newNode0);

		// process terminal symbol 'model' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type==LUTypeKeyword && currentUnit.subtype==KeywordModel)
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized keyword \"model\".");
#endif
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Error. Recovery is to skip this lexic unit.");
#endif
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_MODEL_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <name> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_Name(newNode2);

		// process terminal symbol '(' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type==LUTypeSpecialCharacter && currentUnit.subtype==SpecialCharacterLeftParenthesis)
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterLeftParenthesis.");
#endif
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Error. Recovery is to skip this lexic unit.");
#endif
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <parameters> 
		SyntaxTreeNode * newNode4 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode4);
		Parse_Parameters(newNode4);

		// process terminal symbol ')' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type==LUTypeSpecialCharacter && currentUnit.subtype==SpecialCharacterRightParenthesis)
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterRightParenthesis.");
#endif
			SyntaxTreeNode * newNode5 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode5);
			newNode5->LexUnitID=this->CurrentLexicPosition;
			newNode5->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Error. Recovery is to skip this lexic unit.");
#endif
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <model_definition_in> 
		SyntaxTreeNode * newNode6 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode6);
		Parse_ModelDefinitionIn(newNode6);

		// process nonterminal symbol <model_definition_out> 
		SyntaxTreeNode * newNode7 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode7);
		Parse_ModelDefinitionOut(newNode7);

		// process terminal symbol '{' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type==LUTypeSpecialCharacter && currentUnit.subtype==SpecialCharacterLeftCurlyBrace)
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterLeftCurlyBrace.");
#endif
			SyntaxTreeNode * newNode8 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode8);
			newNode8->LexUnitID=this->CurrentLexicPosition;
			newNode8->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Error. Recovery is to skip this lexic unit.");
#endif
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <model_body> 
		SyntaxTreeNode * newNode9 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode9);
		Parse_ModelBody(newNode9);

		// process terminal symbol '}' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type==LUTypeSpecialCharacter && currentUnit.subtype==SpecialCharacterRightCurlyBrace)
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterRightCurlyBrace.");
#endif
			SyntaxTreeNode * newNode10 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode10);
			newNode10->LexUnitID=this->CurrentLexicPosition;
			newNode10->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Error. Recovery is to skip this lexic unit.");
#endif
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}
	}
	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_MODEL_DEFINITION_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_ModelDefinition");
#endif
}

// <model_definition_in> ~ in ( <label_list> )  {in}
// <model_definition_in> ~ ? {out, {}
void Parser::Parse_ModelDefinitionIn(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_ModelDefinitionIn");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	if(currentUnit.type==LUTypeKeyword && currentUnit.subtype==KeywordIn)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"in\".");
#endif
		// write type of production in this node
		parent->Production = Gr_ModelDefinitionIn__in_spLPar_LabelList_spRPar;

		// process terminal symbol 'in' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process terminal symbol '(' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type==LUTypeSpecialCharacter && currentUnit.subtype==SpecialCharacterLeftParenthesis)
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterLeftParenthesis.");
#endif
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Error. Recovery is to skip this lexic unit.");
#endif
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <label_list> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_LabelList(newNode2);

		// process terminal symbol ')' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis )
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterRightParenthesis.");
#endif
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Error. Recovery is to skip this lexic unit.");
#endif
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}
	}
	else if( (currentUnit.type==LUTypeKeyword && currentUnit.subtype==KeywordOut) ||
		(currentUnit.type==LUTypeSpecialCharacter && currentUnit.subtype==SpecialCharacterLeftCurlyBrace) )
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"out\" or SpecialCharacterLeftCurlyBrace.");
#endif
		// write type of production in this node
		parent->Production = Gr_ModelDefinitionIn__epsilon;
	}
	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_MODEL_DEFINITION_IN_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_ModelDefinitionIn");
#endif
}

// <model_definition_out> ~ out ( <label_list> )  {out}
// <model_definition_out> ~ ? {{}
void Parser::Parse_ModelDefinitionOut(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_ModelDefinitionOut");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	if(currentUnit.type==LUTypeKeyword && currentUnit.subtype==KeywordOut)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"out\".");
#endif
		// write type of production in this node
		parent->Production = Gr_ModelDefinitionOut__out_spLPar_LabelList_spRPar;

		// process terminal symbol 'out' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process terminal symbol '(' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type==LUTypeSpecialCharacter && currentUnit.subtype==SpecialCharacterLeftParenthesis)
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterLeftParenthesis.");
#endif
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Error. Recovery is to skip this lexic unit.");
#endif
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <label_list> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_LabelList(newNode2);

		// process terminal symbol ')' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type==LUTypeSpecialCharacter && currentUnit.subtype==SpecialCharacterRightParenthesis)
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterRightParenthesis.");
#endif
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Error. Recovery is to skip this lexic unit.");
#endif
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}
	}
	else if(currentUnit.type==LUTypeSpecialCharacter && currentUnit.subtype==SpecialCharacterLeftCurlyBrace)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterLeftCurlyBrace.");
#endif
		// write type of production in this node
		parent->Production = Gr_ModelDefinitionOut__epsilon;
	}
	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_MODEL_DEFINITION_OUT_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_ModelDefinitionOut");
#endif
}

// <label_list> ~ ? {)}
// <label_list> ~ default <labels>  {default}
// <label_list> ~ NAME <labels>  {NAME}
void Parser::Parse_LabelList(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_LabelList");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	if(currentUnit.type==LUTypeSpecialCharacter && currentUnit.subtype==SpecialCharacterRightParenthesis)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterRightParenthesis.");
#endif
		// write type of production in this node
		parent->Production = Gr_LabelList__epsilon;
	}
	else if(currentUnit.type==LUTypeKeyword && currentUnit.subtype==KeywordDefault)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"default\".");
#endif
		// write type of production in this node
		parent->Production = Gr_LabelList__default_Labels;

		// process terminal symbol 'default' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <labels> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_Labels(newNode1);
	}
	else if(currentUnit.type==LUTypeIdentifier)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized NAME.");
#endif
		// write type of production in this node
		parent->Production = Gr_LabelList__NAME_Labels;

		// process terminal symbol 'NAME' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <labels> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_Labels(newNode1);
	}
	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LABEL_LIST_BEGINING);
		// MAKE LOGICAL RECOVERING
		this->CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_LabelList");
#endif
}

// <labels> ~ <comma_label> <labels>  {,}
// <labels> ~ ? {)}
void Parser::Parse_Labels(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_Labels");
#endif
	LexicUnit currentUnit;
	// get current lexic unit


	do{
      	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type==LUTypeSpecialCharacter && currentUnit.subtype==SpecialCharacterComma)
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterComma.");
#endif
			// write type of production in this node
			parent->Production = Gr_Labels__CommaLabel_Labels;

			// process nonterminal symbol <comma_label> 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			Parse_CommaLabel(newNode0);

		}
		else if(currentUnit.type==LUTypeSpecialCharacter && currentUnit.subtype==SpecialCharacterRightParenthesis)
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterRightParenthesis.");
#endif
			// write type of production in this node
			parent->Production = Gr_Labels__CommaLabel_Labels;;
			break;
		}
		else
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Error. Recovery is to skip this lexic unit.");
#endif
			// ERROR has been found
			// REPORT ERROR
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LABELS_BEGINING);
			// MAKE LOGICAL RECOVERING
			CurrentLexicPosition++;
			break;
		}
	}while(1);
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_Labels");
#endif
}

// <comma_label> ~ , NAME  {,}
void Parser::Parse_CommaLabel(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_CommaLabel");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	if(currentUnit.type==LUTypeSpecialCharacter && currentUnit.subtype==SpecialCharacterComma)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterComma.");
#endif
		// write type of production in this node
		parent->Production = Gr_CommaLabel__spComma_NAME;

		// process terminal symbol ',' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process terminal symbol 'NAME' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type==LUTypeIdentifier)
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized lexic unit NAME.");
#endif
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Error. Recovery is to skip this lexic unit.");
#endif
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_NAME_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}
	}
	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_COMMA_LABEL_BEGINING);
		// MAKE LOGICAL RECOVERING
		CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_CommaLabel");
#endif
}

// <model_mod> ~ public  {public}
// <model_mod> ~ private  {private}
// <model_mod> ~ ? {model}
void Parser::Parse_ModelMod(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_ModelMod");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	if(currentUnit.type==LUTypeKeyword && currentUnit.subtype==KeywordPublic)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"public\".");
#endif
		// write type of production in this node
		parent->Production = Gr_ModelMod__public;

		// process terminal symbol 'public' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

	}
	else if(currentUnit.type==LUTypeKeyword && currentUnit.subtype==KeywordPrivate)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"private\".");
#endif
		// write type of production in this node
		parent->Production = Gr_ModelMod__private;

		// process terminal symbol 'private' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;
	}
	else if(currentUnit.type==LUTypeKeyword && currentUnit.subtype==KeywordModel)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"model\".");
#endif
		// write type of production in this node
		parent->Production = Gr_ModelMod__epsilon;
	}
	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_MODEL_MOD_BEGINING);
		// MAKE LOGICAL RECOVERING
		CurrentLexicPosition++;
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_ModelMod");
#endif
}
